﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using _404park.Core.Crawler;

namespace _404park.ApplicationServices.Crawler.Parser
{
    public abstract class BaseFeedParser : IFeedParser
    {
        #region Properties

        public abstract string BaseUrl
        {
            get;
        }

        public virtual string Name
        {
            get
            {
                return this.GetType().Name;
            }
        }

        #endregion

        #region Public methods

        public virtual IList<Feed> GetFeeds(string keyword, int start = 0)
        {
            IList<Feed> feedResult = null;
            var feedUrl = "";
            try
            {
                feedUrl = GetFeedUrl(keyword, start);
                var timeOut = 30000;
                var responseData = GetRawResult(feedUrl, timeOut, 0);
                if (!string.IsNullOrEmpty(responseData.Trim()))
                    feedResult = ParseFeed(responseData);
            }
            catch (Exception ex)
            {
                //new Logger.LogError(ex, new NameValueCollection(){
                //    {"FeedParser", this.GetType().Name},
                //    {"FeedUrl", feedUrl}
                //});
            }

            return feedResult;
        }

        public virtual string GetRawResult(string requestUri, int connectionTimeout, int readTimeout)
        {
            string responseData = string.Empty;
            var user_agent = "PowerSearch/1.0";

            var webClient = new TimeOutWebClient(connectionTimeout);
            webClient.Headers.Add("user-agent", user_agent);

            using (var responseStream = webClient.OpenRead(requestUri))
            {
                if (responseStream != null)
                {
                    var responseReader = new StreamReader(responseStream);
                    responseData = responseReader.ReadToEnd();
                }
            }

            return responseData;
        }

        #endregion

        #region Internals methods

        internal virtual string GetFeedUrl(string keyword, int start = 0)
        {
            return string.Format(BaseUrl, keyword);
        }

        protected internal abstract IList<Feed> ParseFeed(string data);

        #endregion
    }

    class TimeOutWebClient : WebClient
    {
        private readonly int _timeout;
        public TimeOutWebClient(int timeout)
            : base()
        {
            _timeout = timeout;
        }

        protected override WebRequest GetWebRequest(Uri address)
        {
            var request = base.GetWebRequest(address);
            request.Timeout = _timeout;
            return request;
        }
    }
}
